/*
 * pc/console-vga.cc - PC VGA console support.
 * Copyright (C) 2007  Mikhail Vorozhtsov
 * See the LICENSE section of the README file for details.
 */

/* $Id$ */

#include HEADER (pc,console-vga.hh)
#include ARCH_HEADER (io.hh)

START_NAMESPACE (pc)

using ARCH::in8;
using ARCH::out8;

#define COLUMNS 80
#define ROWS 25
#define CHARACTER(x,y) (((u16_t *) video_mem)[(y) * COLUMNS + (x)])

static void *video_mem;
static int cur_x, cur_y;

static void
scroll ()
{
  for (int y = 1; y < ROWS; ++y)
    for (int x = 0; x < COLUMNS; ++x)
      CHARACTER (x, y - 1) = CHARACTER (x, y);
  for (int x = 0; x < COLUMNS; ++x)
    CHARACTER (x, ROWS - 1) = 0x0720;
}

void
vga_console::init (void *_video_mem)
{
  video_mem = _video_mem;

  out8 (0x3D4, 0x0F);
  u16_t crs = in8 (0x3D5);
  out8 (0x3D4, 0x0E);
  crs |= in8 (0x3D5) << 8;

  cur_x = crs % COLUMNS;
  cur_y = (crs - cur_x) / COLUMNS;
}

void
vga_console::putc (char c)
{
  if (c == '\n')
    {
      if (cur_y == ROWS - 1)
        scroll ();
      else
        cur_y += 1;
      cur_x = 0;
    }
  else
    if (cur_x < COLUMNS)
      {
        CHARACTER (cur_x, cur_y) = 0x0700 | (u8_t) c;
        cur_x += 1;
      }

  u16_t crs = cur_y * COLUMNS + cur_x;

  out8 (0x3D4, 0x0F);
  out8 (0x3D5, crs & 0xFF);
  out8 (0x3D4, 0x0E);
  out8 (0x3D5, crs >> 8);
}

END_NAMESPACE

